#include "comm.h"
#include "api.h"

// GET  （短指令 获取信息）
// POST （短指令 修改配置）            postman
// 文件传输 （配置文件导入 / 固件升级）   postman
// websocket （实时报文）             postman
// https

struct mg_connection *nc;
static struct mg_serve_http_opts s_http_server_opts;

static mg_route_t mg_route[] = {

    {"GET", "/get_value", api_get_value, false},
    {"POST", "/set_value", api_set_value, false},
};

static mg_upload_t mg_upload[] = {
    // 文件交互接口

    {"/cfg", api_import_cfg},
    {"/plugin", api_update_plugin},
};


static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
{

  struct http_message *hm = (struct http_message *)ev_data;
  struct mg_str method_type;

  switch (ev)
  {
  case MG_EV_HTTP_REQUEST:

    char url[200] = {0};
    memcpy(url,  hm->uri.p, hm->uri.len);
    printf("method:%.*s,url:%s\n", 4, hm->method.p, url);

    int i = 0;
    for (i = 0; i < sizeof(mg_route) / sizeof(mg_route_t); i++)
    {
      method_type.len = strlen(mg_route[i].type);
      method_type.p = mg_route[i].type;

      if (is_equal(&hm->method, &method_type))
      {
        if (strcmp(url, mg_route[i].url) == 0)
        {
          if (mg_route[i].fmethod != NULL)
          {
            char *payload = mg_route[i].fmethod(hm);
            if (payload != NULL)
            {

              mg_printf(nc,
                        "HTTP/1.1 200 OK\r\n"
                        "Content-Type: text/plain\r\n"
                        "Content-Length: %d\r\n\r\n%s",
                        (int)strlen(payload), payload);
              free(payload);
            }
            else
            {
              mg_printf(nc, "%s",
                        "HTTP/1.0 501 Not Implemented\r\n"
                        "Content-Length: 0\r\n\r\n");
            }
          }
          return;
        }
      }
    }

    // 如果代码能执行到这里，说明请求的路由不支持
    mg_printf(nc, "%s",
              "HTTP/1.1 404 Not Found\r\n"
              "Content-Length: 0\r\n\r\n");

    break;
  case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
  {
    printf("joined!\n");
    break;
  }
  case MG_EV_WEBSOCKET_FRAME:
  {
    struct websocket_message *wm = (struct websocket_message *)ev_data;
    /* New websocket message. Tell everybody. */
    // struct mg_str d = {(char *) wm->data, wm->size};
    char buf[500] = {0};
    snprintf(buf, sizeof(buf), "%.*s", (int)wm->size, (char *)wm->data);

    printf("websocket recv:%s\n",buf);

    break;
  }
  case MG_EV_CLOSE:
  {
    /* Disconnect. Tell everybody. */
    if (is_websocket(nc))
    {
      // websocket_stop();
      printf("leave!\n");
    }
    break;
  }
  default:
    break;
  }
}

void *websocket_thread(void *param)
{
  char buffer[100] = {0};

  while (1)
  {
    time_t now = time(NULL);

    struct tm *tm_info = localtime(&now);
    char time_str[26];
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info);
    // printf("websocket thread running at %s\n", time_str);
    // 每隔5秒发送一次心跳包
    
    snprintf(buffer, sizeof(buffer), "{\"type\":\"heartbeat\",\"time\":\"%s\"}", time_str);
    printf("websocket send:%s\n", buffer);
    
    websocket_pkt_send(buffer);

    sleep(5);
  }

  pthread_exit(NULL);
}

int main()
{

  struct mg_mgr mgr;

  /* Open listening socket */
  mg_mgr_init(&mgr, NULL);
  nc = mg_bind(&mgr, "8080", ev_handler);
  if (nc == NULL)
  {
    printf("bind webport:8080 error!");
    return -1;
  }

  int i;
  for (i = 0; i < sizeof(mg_upload) / sizeof(mg_upload_t); i++)
  {
    mg_register_http_endpoint(nc, mg_upload[i].url, mg_upload[i].fupload);
  }
  mg_set_protocol_http_websocket(nc);
  s_http_server_opts.document_root = "./dist";
  s_http_server_opts.enable_directory_listing = "yes";
  /* Run event loop until signal is received */

  printf("HTTP server running on 8000\n");

  // 创建一个线程
  pthread_t thread;
  pthread_create(&thread, NULL, websocket_thread, NULL);
  pthread_detach(thread); // 分离线程

  for (;;)
    mg_mgr_poll(&mgr, 1000); // 事件循环

  /* Cleanup */
  mg_mgr_free(&mgr);

  return 0;
}